/* eslint-disable no-param-reassign */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useNamespace } from '@ibiz-template/vue3-util';
import { computed, defineComponent, Ref, ref } from 'vue';

import './group-pivottable-body.scss';

export const GroupPivotTableBody = defineComponent({
  name: 'IBizGroupPivotTableBody',
  props: {
    groupData: {
      type: Array<IData>,
      required: true,
    },
    colKeys: {
      type: Array<IData>,
      required: true,
    },
    rowKeys: {
      type: Array<IData>,
      required: true,
    },
    rowAttrs: {
      type: Array<string>,
      required: true,
    },
  },
  setup(props) {
    const ns = useNamespace(`group-pivottable-body`);

    const collapseKeys: Ref<string[]> = ref([]);

    const colFields = computed(() => {
      return props.colKeys.map((tags: any) => {
        return tags.join(String.fromCharCode(0));
      });
    });

    const parseRows = (item: IData) => {
      const result: IData = {};
      if (item.items) {
        item.items.forEach((x: IData) => {
          result[x.codeName] = x.format;
        });
      }
      result.pvtTotal = item.format;
      result.srfkey = item.srfkey;
      return result;
    };

    const fillRows = (items: IData[]) => {
      const result: IData[] = [];
      items.forEach((item: IData) => {
        result.push(parseRows(item));
        if (item.children && item.children.length) {
          result.push(...fillRows(item.children));
        }
      });
      return result;
    };

    const fillColKeys = (item: IData) => {
      const keys = Object.keys(item);
      props.colKeys.forEach((tags: any) => {
        const tag = tags.join(String.fromCharCode(0));
        if (!keys.includes(tag)) {
          item[tag] = '';
        }
      });
      return item;
    };

    const rows = computed(() => {
      const items = fillRows(props.groupData);
      const result: IData[] = items.map(x => fillColKeys(x));
      const res = result.filter(x => !collapseKeys.value.includes(x.srfkey));
      return res;
    });

    const calcNodeExpand = (
      data: IData,
      expand: boolean,
      keySet: Set<string>,
    ) => {
      const children = data.children || [];
      if (expand) {
        children.forEach((x: IData) => {
          keySet.delete(x.srfkey);
          if (x.children && x.children.length) {
            calcNodeExpand(x, expand, keySet);
          }
        });
      } else {
        children.forEach((x: IData) => {
          keySet.add(x.srfkey);
          if (x.children && x.children.length) {
            calcNodeExpand(x, expand, keySet);
          }
        });
      }
    };

    const updateNodeExpand = (data: IData, expand: boolean) => {
      const keySet = new Set(collapseKeys.value);
      calcNodeExpand(data, expand, keySet);
      collapseKeys.value = Array.from(keySet);
    };

    const renderRow = (item: IData) => {
      return colFields.value.map(key => {
        return <td>{item[key]}</td>;
      });
    };

    const renderDropdown = (index: number) => {
      if (index !== 0) {
        return;
      }
      const content = (
        <el-tree
          data={props.groupData}
          default-expand-all
          onNodeExpand={(data: IData) => {
            updateNodeExpand(data, true);
          }}
          onNodeCollapse={(data: IData) => {
            updateNodeExpand(data, false);
          }}
        />
      );
      return (
        <th rowspan={rows.value.length} colspan={props.rowAttrs.length + 1}>
          {content}
        </th>
      );
    };
    return {
      ns,
      rows,
      renderRow,
      renderDropdown,
    };
  },
  render() {
    return this.rows.map((column: IData, index: number) => {
      return (
        <tr class={this.ns.b()}>
          {this.renderDropdown(index)}
          {this.renderRow(column)}
        </tr>
      );
    });
  },
});
